﻿
// 2019/1/18: 首个记录
// 2019/3/29: 添加注释
// 2019/10/11: 修改include
// 2020/11/2: 修改卫星时间注释

#ifndef GNSSIMU_SAMPLE_V5_H
#define GNSSIMU_SAMPLE_V5_H

#include "spadas.h"

namespace gnssimu_sample_v5
{
	using namespace spadas;

	enum GnssImuLocationMode
	{
		GILM_NoLocation = 0, //无位置信息
		GILM_Normal = 1, //默认模式
		GILM_RTKFixed = 2, //RTK固定解
		GILM_RTKFloat = 3, //RTK浮动解
		GILM_RTD = 4, //RTD
	};

	struct GnssImuSample
	{
		GlobalTimestamp timeStamp; // 时间戳

		GnssImuLocationMode locationMode; //位置模式

		OptionalDouble longitude; // 经度 deg 东经为正
		OptionalDouble latitude; // 纬度 deg 北纬为正
		OptionalDouble altitude; // 海拔 m
		OptionalDouble speed; // 车速 kph
		OptionalDouble orientation; // 朝向 deg CCW为正, 北为0, -180~180

		OptionalDouble pitch; // 俯仰角 deg 车头朝下为正
		OptionalDouble roll; // 横滚角 deg 右侧朝下为正
		OptionalDouble yawRate; // 横摆角速度 deg/s CCW为正
		OptionalDouble ax; // 纵向加速度 m/s2 朝前为正
		OptionalDouble ay; // 横向加速度 m/s2 朝左为正
		OptionalDouble az; // 天向加速度 m/s2 朝上为正

		Optional<Time> gnssTime; // 卫星UTC时间
		OptionalInt gnssTimeMS;

		GnssImuSample()
		{
			locationMode = GILM_NoLocation;
		}

		static String getProtocolName(UInt channel)
		{
			return (String)"gnssimu-sample-v5@" + channel;
		}

		static String getTitle()
		{
			return "Location mode,Longitude[°],Latitude[°],Altitude[m],Speed[KPH],Orientation[°],Pitch angle[°],Roll angle[°],Yaw rate[°/s],Acceleration-x[m/s2],Acceleration-y[m/s2],Acceleration-z[m/s2],Year,Month,Day,Hour,Minute,Second,Millisecond";
		}

		Bool fromGeneralSample(GeneralSample sample)
		{
			if (sample.values.size() != 19) return FALSE;

			timeStamp = sample.timeStamp;

			locationMode = sample.values[0].valid ? (GnssImuLocationMode)(Int)sample.values[0].value : GILM_NoLocation;
			longitude = sample.values[1];
			latitude = sample.values[2];
			altitude = sample.values[3];
			speed = sample.values[4];
			orientation = sample.values[5];
			pitch = sample.values[6];
			roll = sample.values[7];
			yawRate = sample.values[8];
			ax = sample.values[9];
			ay = sample.values[10];
			az = sample.values[11];

			if (sample.values[12].valid &&
				sample.values[13].valid &&
				sample.values[14].valid &&
				sample.values[15].valid &&
				sample.values[16].valid &&
				sample.values[17].valid &&
				sample.values[18].valid)
			{
				gnssTime = Time((UInt)sample.values[12].value,
					(UInt)sample.values[13].value,
					(UInt)sample.values[14].value,
					(UInt)sample.values[15].value,
					(UInt)sample.values[16].value,
					(UInt)sample.values[17].value);
				gnssTimeMS = (Int)sample.values[18].value;
			}
			else
			{
				gnssTime = Optional<Time>();
				gnssTimeMS = OptionalInt();
			}

			return TRUE;
		}
		GeneralSample toGeneralSample()
		{
			GeneralSample sample;
			sample.timeStamp = timeStamp;
			sample.values = Array<OptionalDouble>(19);
			OptionalDouble *data = sample.values.data();

			data[0] = (Double)(Int)locationMode;
			data[1] = longitude;
			data[2] = latitude;
			data[3] = altitude;
			data[4] = speed;
			data[5] = orientation;
			data[6] = pitch;
			data[7] = roll;
			data[8] = yawRate;
			data[9] = ax;
			data[10] = ay;
			data[11] = az;
			data[12] = gnssTime.isValid() ? gnssTime.refValue().year : OptionalDouble();
			data[13] = gnssTime.isValid() ? gnssTime.refValue().month : OptionalDouble();
			data[14] = gnssTime.isValid() ? gnssTime.refValue().day : OptionalDouble();
			data[15] = gnssTime.isValid() ? gnssTime.refValue().hour : OptionalDouble();
			data[16] = gnssTime.isValid() ? gnssTime.refValue().minute : OptionalDouble();
			data[17] = gnssTime.isValid() ? gnssTime.refValue().second : OptionalDouble();
			data[18] = gnssTimeMS.valid ? gnssTimeMS.value : OptionalDouble();

			sample.significantCount = 19;
			return sample;
		}
	};
}

#endif
